#!/bin/perl -w

# $Header: /opt/unixmon/tools/DNS/RCS/named_sync_slaves.pl,v 1.111 2012/11/27 08:02:58 yang Exp $

# Author: yang.jin@ebay.com 
#
# this script reads zone defination (part of named configuration) on a master DNS server, 
# and produces zone defination for slave DNS servers. And then, copies the zone defination
# files to slaves, and reloads named on the slaves.
#
# this script must be called by a script "named_sync_slaves", and cannot be executed 
# independently.
# 
# =====================================================================================

use strict;
use Env;
use File::Basename;

# ROOT & RUN for the purpose of testing
# my $ROOT	= "/MINE";
# my $RUN	= "# ";

my $ROOT	= "";
my $RUN		= "";


my $NAMEDCHECKCONF	= '/opt/bind/sbin/named-checkconf';
my $RSYNC	= "/usr/local/bin/rsync";
my $RNDC	= "$RUN" . "/opt/bind/sbin/rndc";
my $SSH		= "/bin/ssh";

# configuration files need to be converted for slaves, replacing "masters" in the zones with ITS Masters
my @SLAVE_SITES= qw/ 
			its
			mp
			base
			misc
			qa
		  /;

# master zones are to be synced, including configuration and zone DBs
# "root" DBs are skipped.
my @MASTER_SITES= qw/
		bl
		/;	

# only configuraton is to be synced for "nodb", it includes "forward" and "stub" zones only
my @NODB_SITES = qw/
		nodb
		/;

# my @IT_MASTERS = ("10.58.10.16", "10.58.10.15"); 
my @IT_MASTERS = ("10.101.155.16", "10.101.155.15"); 

my $cfgbasedir	= $ROOT . "/etc/named";
my $dbbasedir	= $ROOT . "/var/named/db";
my $tmpbasedir	= $ROOT . "/var/named/tmp";

# =====================================================================================
# ==================== Start of MAIN ==================================================


my $len = @ARGV;

if ( $len != 2 and $len != 4 ) { print_usage(); exit 1; }

my ($option1, $para1, $option2, $para2) = @ARGV;

if ( $len == 2 ) { $option2 = "-d"; $para2 = "all"; }

if ( $option1 ne "-s" || $option2 ne "-d" ) { print_usage(); exit 1; }

my @sites; 
if ( $para1 eq "all" ) { @sites = (@SLAVE_SITES, @MASTER_SITES, @NODB_SITES); } 
else {
	$para1 =~ s/^\s+//;
	$para1 =~ s/\s+$//;
	@sites = split(/\s+/, $para1);

	# verify each site
	my $tmpsite;
	my $invalidsite = 0;
	foreach $tmpsite (@sites) {
		my $isdefined = 0;
		foreach (@SLAVE_SITES, @MASTER_SITES, @NODB_SITES) {
			if ( $_ eq $tmpsite ) { $isdefined = 1; }
		}
		if ( $isdefined == 0 ) {
			$invalidsite = 1; 
			printf STDERR "\nERROR: \"%s\" is not a valid site.\n", $tmpsite; 
		}
	}

	if ( $invalidsite == 1 ) { print_usage(); exit 1; }
}


my @slaves; 
my @SLAVE_SERVERS;
my $aa; 

if ( $para2 eq "all" ) { 
	$aa = defined($DNS_SLAVES) ? $DNS_SLAVES : "";
	# printf STDERR "DNS_SLAVES:%s:DNS_SLAVES\n", $DNS_SLAVES;
	# if ( $aa ne "" ) {
	chomp($DNS_SLAVES);
	$DNS_SLAVES =~ s/^\n\s*//g;
	$DNS_SLAVES =~ s/\s+$//g;
	$DNS_SLAVES =~ s/\n\s+/ /g;
	printf STDERR "DNS_SLAVES:%s:DNS_SLAVES\n", $DNS_SLAVES;
	@SLAVE_SERVERS = split(/ /, $DNS_SLAVES);
	@slaves = @SLAVE_SERVERS; 
	#}
	#else {
	#	@SLAVE_SERVERS = ();
	#	@slaves = @SLAVE_SERVERS; 
	#}
} 
else {
	$para2 =~ s/\n//g;
	$para2 =~ s/^\s*//g;
	$para2 =~ s/\s+$//g;
	@slaves = split(/\s+/, $para2);

#	# verify each slave
#	my $tmpslave;
#	my $invalidslave = 0;
#	my $tmps;
#	foreach $tmpslave (@slaves) {
#		my $isdefined = 0;
#		# $tmpslave =~ s/\..*//;
#		foreach (@SLAVE_SERVERS) {
#			$tmps = $_;
#			$tmps =~ s/\s*//g;
#			printf STDERR "\nMMMM: \"%s\" is a valid slave server.\n", $tmps; 
#			# $tmps =~ s/\..*//;
#			if ( $tmps eq $tmpslave ) { $isdefined = 1; }
#		}
#		if ( $isdefined == 0 ) {
#			$invalidslave = 1; 
#			printf STDERR "\nERROR: \"%s\" is not a valid slave server.\n", $tmpslave; 
#		}
#	}
#
#	if ( $invalidslave == 1 ) { print_usage(); exit 1; }
}


# start to prepare configuration files/dbs for slave servers

# create a temp dir to store configuraton files
my $dir = $tmpbasedir . "/" . "$$";
`/bin/mkdir -p $dir`;
 
my $site;
my $db2bdist = "";

printf STDOUT "\nGenerating zone configuration files in %s ...\n", $dir;

foreach $site (@sites) {
# master - root/bl, rsync source configuration files and DB directories
	foreach (@MASTER_SITES) {
		if ($site eq $_) {
			printf STDOUT "\tCopying %s/%s.zones to %s ...\n", $cfgbasedir, $site, $dir; 
			`/bin/cp -p $cfgbasedir/$site.zones $dir`;
			if ($db2bdist) { $db2bdist = $db2bdist . " " . $site; }
			else { $db2bdist = $site; }	
		}
	}
	 
# slave - its mp pp base misc qa, convert source configuration files & 
# 	store them under /var/named/tmp? make a temp dir? rsync one by one?
	foreach (@SLAVE_SITES) {
		if ($site eq $_) {
			printf STDOUT "\tCreating %s/%s.zones ...\n", $dir, $site; 
			#`/bin/cp -p $cfgbasedir/$site.zones $dir/$site.slave`;
			convert2slave($site, $dir);
		}
	}

# nodb - nodb, rsync source configuration files only
	foreach (@NODB_SITES) {
		if ($site eq $_) {
			printf STDOUT "\tCopying %s/%s.zones to %s ...\n", $cfgbasedir, $site, $dir; 
			`/bin/cp -p $cfgbasedir/$site.zones $dir`;
		}
	}
	 
} 
# end to prepare configuration files/dbs for slave servers

my $vericode = 0;
printf STDOUT "\nVerifying zone configuration files in %s ...\n", $dir;
foreach $site (@sites) {
	printf STDOUT "\tVerifying %s/%s.zones ...", $dir, $site;
	`$NAMEDCHECKCONF $dir/$site.zones`;
	if ( $? != 0 ) { 
		$vericode = $?; 
		printf STDOUT "\tFailed with exit code %d.\n", $vericode;
	}
	else { printf STDOUT "\tPassed.\n"; }
}

if ( $vericode != 0 ) { 
	printf STDERR "\n\nSyntax checking failed. Run \"named-checkconf\" for details.\n\n"; 
	exit 1;
}


# distriute configuation files and DB files if any
printf STDOUT "\nDistributing zone configuration files and DB files if any to slave DNS servers ...\n"; 
my $slave;
foreach $slave (@slaves) {
	printf STDOUT "\tCopying zone configuration files for sites(%s) to %s ...\n", join(" ", @sites), $slave; 
#	`cd $dir; /bin/tar cf - . | /bin/ssh $slave "cd $cfgbasedir; tar xf -"`;

	open(TMPFILE, "> $tmpbasedir/bash1.$$") || die "\nFailed to open file \"$tmpbasedir/bash1.$$\", exited.\n"; 
	printf TMPFILE "cd %s; /bin/tar cf - . | /bin/ssh %s \"cd %s; /bin/tar xf -\" 2>/dev/null\n", $dir, $slave, $cfgbasedir;
	close(TMPFILE); 

	`/bin/bash $tmpbasedir/bash1.$$`;

	if ($db2bdist) {
		printf STDOUT "\tCopying zone DB files under %s for sites(%s) to %s ...\n", $dbbasedir, $db2bdist, $slave; 
#		`cd $dbbasedir; /bin/tar cf - $db2bdist | /bin/ssh $slave "cd $dbbasedir; tar xf -"`;  
		open(TMPFILE, "> $tmpbasedir/bash2.$$") || die "\nFailed to open file \"$tmpbasedir/bash2.$$\", exited.\n"; 
		printf TMPFILE "cd %s; /bin/tar cf - %s | /bin/ssh %s \"cd %s; /bin/tar xf -\" 2>/dev/null\n", $dbbasedir, $db2bdist, $slave, $dbbasedir;
		close(TMPFILE); 
		`/bin/bash $tmpbasedir/bash2.$$`;
	}
}

# reload named
printf STDOUT "\nReloading DNS configuration on slave DNS servers ...\n"; 
foreach $slave (@slaves) {
	printf STDOUT "\tReloading configuration on %s...\n", $slave; 
	`$SSH $slave "$RNDC reconfig" 2>/dev/null`;
}

printf STDOUT "\nRenaming %s to %s.old ...\n", $dir, $dir;
`/bin/mv $dir $dir.old`;


printf STDOUT "\n==========================================================================\n";
printf STDOUT "\nReminder: Run \"nslookupall\" and \"named_status\" to verify status of DNS servers.\n\n";


# ==================== End of MAIN ====================================================
# =====================================================================================

# -------------------------------------------------------------------------------------
sub convert2slave {
  my ($site, $dir) = @_;

  my $sfile = "$cfgbasedir" . "/" . $site . ".zones";
  my $tfile = "$dir" . "/" . $site . ".zones";

  my @lines = fgetlines($sfile); 

  open(TFILE,"> $tfile") || die "\nFailed to open file \"$tfile\", exited.\n";

  my $zoneclause= "";
  my $zone;
  my $type;
  my $file; 

  my @mservers;
  my $masters;

  my $pip;

  foreach (@lines) {
        chomp;
        $_ =~ s/(\/\/|#).*//;   # remove the notes
        $_ =~ s/\/\*.*\*\///;   # remove the notes
        $_ =~ s/\s+/ /g;

        $_ =~ s/ *allow\-transfer \{(.*)\} *\;//;
        $_ =~ s/ *allow\-update \{(.*)\} *\;//;
        $_ =~ s/ *allow\-query \{(.*)\} *\;//;
        $_ =~ s/ *notify [\d\.\w]+ *\;//;

        $_ =~ s/\" in \{/\" \{/i;  # remove "in" following the zone name

        if ( /^\s+$/ ) { $_ = ""; next; }
        
        if ( /^\s*zone\s/ ) {
                if ( $zoneclause ) { 
			printf STDERR "\nError: failed to analyze zone clause on %s: %s\n", $sfile, $zoneclause; 
			$zoneclause = $_; 
		}
                else { $zoneclause = "$zoneclause" . "$_"; }
        } 
        else {
                if ( $zoneclause ) { $zoneclause = "$zoneclause" . "$_"; }
                else  { next; }
        }
        
        $_ = $zoneclause; 

        if ( / *zone \"(.*)\" \{ *type slave *\; *masters \{(.*)\} *\; *file \"(.*)\"\ *; *\} *\;/ ) {
                $type = "slave";
                $zone = $1;

                $_ = $zone;
                if ( /\.in\-addr\.arpa$/ ) { 
                        $pip = $_;
                        $pip =~ s/\.in\-addr\.arpa$//;
                        $pip = join(".", reverse split(/\./, $pip));
                        $file = "named.rev-" . $pip;
                }
                else { $file = "db." . $zone; }

                $file = $site . "/" . $file; 

		@mservers = @IT_MASTERS;
                
                print_slave($zone, $type, $file, @mservers);
                $_ = $zoneclause = "";
        }
        elsif ( / *zone \"(.*)\" \{ *type stub *\; *masters \{(.*)\} *\; *file \"(.*)\" *\; *\} *\;/ ) {
                $type = "stub";
                $zone = $1;

                @mservers = split("/", $masters);

                $_ = $zone;
                if ( /\.in\-addr\.arpa$/ ) { 
                        $pip = $_;
                        $pip =~ s/\.in\-addr\.arpa$//;
                        $pip = join(".", reverse split(/\./, $pip));
                        $file = "named.rev-" . $pip;
                }
                else { $file = "db." . $zone; }
                
                $file = $site . "/" . $file; 

                print_slave($zone, $type, $file, @mservers);
                $_ = $zoneclause = "";
        }
        elsif ( / *zone \"(.*)\" \{ *type forward *\; *forwarders \{(.*)\} *\; *\} *\;/ ) {
                $type = "forward";
                $zone = $1;

                $masters = $2;
                $file = "\-";
                $masters =~ s/\s+//g;
                $masters =~ s/\;$//;
                $masters =~ s/\;/\//g;

                @mservers = split("/", $masters);

                print_forward($zone, $type, @mservers);
                $_ = $zoneclause = "";
        }
        elsif ( / *zone \"(.*)\" \{ *type hint *\; *file \"(.*)\" *\; *\} *\;/ ) {
                $type = "hint";
                $zone = $1;

                $masters = "localhost";
                $file = $2;

                print_master($zone, $type, $file); 
                $_ = $zoneclause = "";
        }
        elsif ( / *zone \"(.*)\" \{ *type master *\; *file \"(.*)\" *\; *\} *\;/ ) {

                $zone = $1;

                $type = "slave"; 
                @mservers = @IT_MASTERS;

                $_ = $zone;
                if ( /\.in\-addr\.arpa$/ ) { 
                        $pip = $_;
                        $pip =~ s/\.in\-addr\.arpa$//;
                        $pip = join(".", reverse split(/\./, $pip));
                        $file = "named.rev-" . $pip;
                }
                else { $file = "db." . $zone; }

                $file = $site . "/" . $file; 

                print_slave($zone, $type, $file, @mservers);
                $_ = $zoneclause = "";

        }
        else { 
                next;
        }

  }  # end of foreach (@lines)


  close(TFILE);
}

# -------------------------------------------------------------------------------------
sub fgetlines {
	my ($file) = @_;
	my @data = ();
	open(FILE,"< $file") || die "Failed to open file \"$file\".\n";
	@data = <FILE>;
	close(FILE);
	return @data;
}

# -------------------------------------------------------------------------------------
sub print_usage {

	my $site;

	printf STDERR "\nUsage:\n\t%s -s sites [-d slave-servers]\n", &File::Basename::basename($0); 
	#printf STDERR "\nUsage:\n\t%s -s sites [-d slave-servers]\n", $0; 

	printf STDERR "\n\t\"sites\" could be \"all\", otherwise, one or combination of the following:\n"; 
	foreach (@SLAVE_SITES, @MASTER_SITES, @NODB_SITES) { 
		printf STDERR "\t\t%s\n", $_;
	}

	printf STDERR "\n\t\"slave-servers\" could be \"all\", otherwise, one or combination of the following:\n";
	foreach (@SLAVE_SERVERS) { 
		printf STDERR "\t\t%s\n", $_;
	}

	printf STDERR "\nExamples:\n";
	printf STDERR "\n  Propagate changes to misc.zones and nodb.zones onto sjcitdns03 and sjcitdns04 -\n";	
	printf STDERR "\t%s -s \"misc nodb\" -d \"sjcitdns03 sjcitdns04\"\n", &File::Basename::basename($0); 

	printf STDERR "\n  Propagate changes to its.zones onto all slave servers -\n";	
	printf STDERR "\t%s -s its -d all\n", &File::Basename::basename($0); 
	printf STDERR "    or,\n\t%s -s its \n\n", &File::Basename::basename($0); 
	
}

# -------------------------------------------------------------------------------------
sub print_master {

my ($zone, $type, $file) = @_; 

  printf TFILE "zone \"%s\" \{\n", $zone;
  printf TFILE "\ttype %s\;\n", $type;
  printf TFILE "\tfile \"%s\"\;\n\}\;\n\n", $file;

}
# -------------------------------------------------------------------------------------
sub print_slave {

my ($zone, $type, $file, @masters) = @_; 

  printf TFILE "zone \"%s\" \{\n", $zone;
  printf TFILE "\ttype %s\;\n", $type;
  printf TFILE "\tmasters \{ ";

  foreach (@masters) {
        printf TFILE "%s\; ", $_;
  }

  printf TFILE "\}\;\n";
  printf TFILE "\tfile \"%s\"\;\n\}\;\n\n", $file;

}
# -------------------------------------------------------------------------------------
sub print_forward {

my ($zone, $type, @fowarders) = @_; 

  printf TFILE "zone \"%s\" \{\n", $zone;
  printf TFILE "\ttype %s\;\n", $type;
  printf TFILE "\tforwarders \{ ";

  foreach (@fowarders) {
        printf TFILE "%s\; ", $_;
  }

  printf  TFILE "\}\;\n\}\;\n\n";

}
# -------------------------------------------------------------------------------------
# -----------------------------------
### 
### foreach (@szonecfgs) {
### 	if ( -e "$basedir/slave-$_" ) {
###     		print STDERR "$basedir/slave-$_ exists. Please verify whether another process is running or rename the file and then rerun the program.\n";
### 		exit 1;
### 	}
### }
### 
### printf STDOUT "----------------------------------------------------------------------------------------------------------------\n";
### build_slave_configs(@szonecfgs);
### 
### printf STDOUT "----------------------------------------------------------------------------------------------------------------\n";
### check_syntax(@szonecfgs);
### 
### printf STDOUT "----------------------------------------------------------------------------------------------------------------\n";
### copy_config_to_slaves(@slaveservers); 
### 
### printf STDOUT "----------------------------------------------------------------------------------------------------------------\n\n";
### foreach (@slaveservers) {
###         my $server = $_;
### 	printf STDOUT "Reloading named on\t%-27s...\t", $server;
###  	`$SSH $server '$RNDC reload'`;
### 	printf STDOUT "Done.\n";
### }
### 
### printf STDOUT "\n----------------------------------------------------------------------------------------------------------------\n\n";
### foreach (@szonecfgs) {
### 	my $scfg = $basedir . "/slave-" . $_; 
### 	my $tcfg = $basedir . "/slave-" . $_ . ".old"; 
### 	printf STDOUT "Renaming\t%-23s\tto\t%-27s...\t", $scfg, $tcfg;
### 	`/bin/mv $basedir/slave-$_ $basedir/slave-$_.old`;
###   	printf STDOUT "Done.\n";
### }
### 
### printf STDOUT "----------------------------------------------------------------------------------------------------------------\n\n";
### printf STDOUT "\n\nVerification\n============\nPlease run the following 2 command lines to verify if slave DNS servers are functioning:\nfor s in";
### foreach (@slaveservers) { printf STDOUT " $_"; }
### printf STDOUT "; do echo; echo; echo \$s; ssh \$s \"$RNDC status\"\; done\n";
### 
### printf STDOUT "for s in";
### foreach (@slaveservers) { printf STDOUT " $_"; }
### printf STDOUT "; do echo; echo; echo \$s; ssh \$s \"nslookup sjcitdns01.sjc.ebay.com localhost\"\; done\n\n";
### 
### # ====================== End of MAIN ==================================================
### # =====================================================================================
### 
### 
### sub build_slave_configs {
### 
###  my @zonecfg = @_;
### 
###  printf STDOUT "\n";
###  foreach (@zonecfg) {
###   my $zones = $_;
###   open(OUT, ">$basedir/slave-$zones") || die "open $basedir\/slave-$zones.\n";
### 
###   my $scfg = $basedir . "/slave-" . $_; 
###   my $tcfg = $basedir . "/" . $_; 
###   printf STDOUT "Generating configuration %-23s for %-23s on slave servers...\t", $scfg, $tcfg;
### 
###   my @lines = fgetlines("$basedir/$zones");
###   my $mastersstatement = "";
###   my $braces = 0;
###   my $zone = "";
### 
###   foreach (@lines) {
### 
###     if ( /^\s*zone\s+\"(.*)\"/ ) { $zone = $1; }
### 
###     if ( $mastersstatement ) {
### 	chomp;
### 	$_ =~ s/(\/\/|#).*//;   # remove the notes
### 	$_ =~ s/\/\*.*\*\///g;
### 	if ( /\{/  ) {
### 		if ( $braces == 0 ) { $braces = 1; }
### 		else { 
### 			print STDERR "\nUnable to analyse the syntax of the following lines in $basedir/$zones :\n$mastersstatement\n$_";
### 			print STDERR "If you\'re sure that the syntax is correct, please contact the author.\n";
### 			exit 1;
### 		}
### 	}
### 	if ( /\};/ ) {
### 		if ( $braces == 1 ) { $braces = 2; }	
### 		else {
### 			print STDERR "\nUnable to analyse the syntax of the following lines in $basedir/$zones :\n$mastersstatement\n$_";
### 			print STDERR "If you\'re sure that the syntax is correct, please contact the author.\n";
### 			exit 1;
### 		}
### 	}
### 	if ( ! /^\s*$/ ) {
### 		$mastersstatement = "$mastersstatement" . "$_";
### 	}
###     	if ( $braces == 2 ) {  
### 		$_ = "$mastersstatement\n";
### 		$mastersstatement = "";
### 		$braces = 0;
###     	}
###     }
### 
###     if ( ! $mastersstatement ) { 
### 
### 	# don't make any changes to an exceptional zone "127.in-addr.arpa"
### 	if ( $zone eq "127.in-addr.arpa" ) { print OUT "$_"; }
### 
### 	elsif ( /^\s*type\s+master;/x ) {
### 		$_ =~ s/^\s*type\s+master;\s+/\ttype slave;/; 
### 		print OUT "$_\n";
### 		print OUT "\tmasters { $itmasters };\n";
### 	}
### 	elsif ( /^\s*masters\s+\{\s*(\d+\.\d+\.\d+\.\d+;\s*)+\s*\};/x ) {
### 		 $_ =~ s/^\s*masters\s+\{.*\}/\tmasters \{ $itmasters \}/; 
### 		print OUT "$_";
### 	}
### 	elsif ( /^\s*masters\s+\{.*\};/x ) {
### 		print STDERR "\nUnable to analyse the syntax of the following line in $basedir/$zones :\n$_";
### 		print STDERR "If you\'re sure that the syntax is correct, please contact the author.\n";
### 		die;
### 	}
### 	elsif ( /^\s*masters/x ) {
### 		chomp;
### 		$_ =~ s/(\/\/|#).*//;   # remove the notes
### 		$_ =~ s/\/\*.*\*\///g;
### 		$mastersstatement = $_;
### 		if ( /\{/ ) { $braces = 1; }
### 		# if the statement "masters { };" is on different lines.
### 	}
### 	else { print OUT "$_"; }
###     } # end of if ! ( $mastersstatement )
###   } # end of foreach (@lines)
### 
###   printf STDOUT "Done.\n";
###  } # end of foreach (@zonecfg) 
###  printf STDOUT "\n";
###  close(OUT);
### }
### 

### sub check_syntax {
### 	my (@files) = @_;
### 
### 	printf STDOUT "\n";
### 	foreach (@files) {
### 		my $file = "$basedir/slave-" . "$_";
### 		$_ = $file;
### 		printf STDOUT "Checking configuration syntax on %-23s...\t", $_;
### 		my $output = `$NAMEDCHECKCONF $_`;
### 		if ($? == 0 ) { printf STDOUT "Passed.\n";}
### 		elsif ($? == 1) {
### 			printf "child exited with value %d\n", $? >> 8;
### 			print "$output\n";
### 			print "Please correct and run again\n";
### 			exit 1;
### 		}
### 		elsif ($? == -1) {
### 			print "Unable to validate  $_ with $NAMEDCHECKCONF\n"; 
### 			die "failed to execute: $!\n";
### 			exit 1;
### 		}
### 		elsif ($? & 127) {
### 			printf "child died with signal %d, %s coredump\n",
### 				($? & 127),  ($? & 128) ? 'with' : 'without';
### 			exit 1;
### 		}
### 		else {
### 			printf "child exited with value %d\n", $? >> 8;
### 			print "unknown exit code please investigate syntax " . 
### 				"for $_ with $NAMEDCHECKCONF\n";
### 			exit 1;
### 
### 		}
### 	}
### 	printf STDOUT "\n";
### }
### 
### sub copy_config_to_slaves {
### 
### my @slaves = @_;
### 
###   printf STDOUT "\n";
###   foreach (@slaves) {
### 	my $server = $_;
### 	foreach (@szonecfgs) {
### 		my $scfg = $basedir . "/slave-" . $_; 
### 		printf STDOUT "Synchronizing\t%-23s\tto\t%-28s...\t", $scfg, $server;
### 		`$RSYNC $basedir/slave-$_ $server:$basedir/$_`;
### 	  	printf STDOUT "Done.\n";
### 	}
### 
### 	my $scfg = $basedir . "/" . $blconfig; 
### 	printf STDOUT "Synchronizing\t%-23s\tto\t%-28s...\t", $scfg, $server;
### 	`$RSYNC $basedir/$blconfig $server:$basedir/$blconfig`;
### 	printf STDOUT "Done.\n";
### 
### 	printf STDOUT "Synchronizing\t%-23s\tto\t%-28s...\t",$bldb,$server;
### 	$_ = $bldb;
### 	s/\/(\w+)$//;
### 	`$RSYNC -a $bldb $server:$_`;
### 	printf STDOUT "Done.\n\n";
###    }
### }
